using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.EventSystems;
using Voodoo.Sauce.Core;
using Voodoo.Sauce.Internal;

namespace Voodoo.Sauce.Tools.AccessButton
{
	public class BubbleButton : MonoBehaviour, IPointerDownHandler, IEventSystemHandler, IPointerUpHandler, IBeginDragHandler, IDragHandler, IEndDragHandler
	{
		public bool forceUpsideDown;

		public CanvasGroup canvasGroup;

		public RectTransform parentRT;

		public RectTransform myRect;

		public RectTransform hideArea;

		private bool _isUsable = true;

		private const float MAXSize = 1.5f;

		private const float DistanceHide = -1200f;

		private bool _isDragged;

		private Vector3 _startMousePos;

		private Vector3 _startPos;

		private bool _isXRestrict;

		private bool _isYRestrict;

		private float _fakeX;

		private float _fakeY;

		private float _halfWidth;

		private float _halfHeight;

		private Vector3 _endLerpPosition;

		private Vector3 _startLerpPosition;

		private const float DurationLerp = 0.1f;

		private EventSystem _eventSystem;

		private static CancellationTokenSource _mouseDownCts;

		private const string TAG = "AccessButton";

		private void Start()
		{
			_eventSystem = EventSystem.current;
			if (_eventSystem == null)
			{
				VoodooLog.LogDebug(Module.COMMON, "AccessButton", "No EventSystem on the scene. Add an EventSystem to use the Access Button");
			}
			Rect rect = myRect.rect;
			_halfWidth = rect.width / 2f;
			_halfHeight = rect.height / 2f;
			GroupVisibility(show: true);
		}

		private void Update()
		{
			if (!_isUsable && (Input.deviceOrientation == DeviceOrientation.PortraitUpsideDown || forceUpsideDown))
			{
				forceUpsideDown = false;
				ShowButtonUI();
			}
		}

		private void SetUpLerp()
		{
			_startLerpPosition = myRect.localPosition;
			if (myRect.localPosition.x <= 0f)
			{
				_endLerpPosition = new Vector3(parentRT.rect.xMin + _halfWidth, _startLerpPosition.y, _startLerpPosition.z);
			}
			else if (myRect.localPosition.x > 0f)
			{
				_endLerpPosition = new Vector3(parentRT.rect.xMax - _halfWidth, _startLerpPosition.y, _startLerpPosition.z);
			}
		}

		private async void HideButtonUI()
		{
			_isUsable = false;
			while (myRect.transform.localPosition.y > -1200f)
			{
				myRect.transform.localPosition -= new Vector3(0f, 100f, 0f);
				await Task.Delay(1);
			}
			myRect.transform.localPosition = new Vector3(0f, -1200f, 0f);
			GroupVisibility(show: false);
		}

		private async void ShowButtonUI()
		{
			GroupVisibility(show: true);
			myRect.transform.localPosition = new Vector3(0f, -200f, 0f);
			SetUpLerp();
			await Task.Delay(500);
			EndOfDragBehavior();
			await Task.Delay(500);
			_isUsable = true;
		}

		private async void EndOfDragBehavior()
		{
			float time = 0f;
			_mouseDownCts = new CancellationTokenSource();
			while (!_mouseDownCts.IsCancellationRequested)
			{
				Resize();
				if (time < 0.1f)
				{
					base.transform.localPosition = Vector3.Lerp(_startLerpPosition, _endLerpPosition, time / 0.1f);
					time += Time.deltaTime;
				}
				else
				{
					base.transform.localPosition = _endLerpPosition;
					_mouseDownCts.Cancel();
				}
				await Task.Delay(1);
			}
			KeepInsideScreen();
		}

		private void Resize()
		{
			if (base.transform.localScale.x > 1f)
			{
				base.transform.localScale -= new Vector3(0.2f, 0.2f, 0.2f);
			}
			else
			{
				base.transform.localScale = new Vector3(1f, 1f, 1f);
			}
		}

		private void KeepInsideScreen()
		{
			if (myRect.localPosition.x < parentRT.rect.xMin + _halfWidth - 1f || myRect.localPosition.x > parentRT.rect.xMax - _halfWidth + 1f)
			{
				_isXRestrict = true;
			}
			else
			{
				_isXRestrict = false;
			}
			if (myRect.localPosition.y < parentRT.rect.yMin + _halfHeight || myRect.localPosition.y > parentRT.rect.yMax - _halfHeight)
			{
				_isYRestrict = true;
			}
			else
			{
				_isYRestrict = false;
			}
			if (_isXRestrict)
			{
				if (myRect.localPosition.x < 0f)
				{
					_fakeX = parentRT.rect.xMin + _halfWidth;
				}
				else
				{
					_fakeX = parentRT.rect.xMax - _halfWidth;
				}
				myRect.localPosition = new Vector3(_fakeX, myRect.localPosition.y, 0f);
			}
			if (_isYRestrict)
			{
				if (base.transform.localPosition.y < 0f)
				{
					_fakeY = parentRT.rect.yMin + _halfHeight;
				}
				else
				{
					_fakeY = parentRT.rect.yMax - _halfHeight;
				}
				myRect.localPosition = new Vector3(base.transform.localPosition.x, _fakeY, 0f);
			}
		}

		private void GroupVisibility(bool show)
		{
			canvasGroup.interactable = show;
			canvasGroup.alpha = (show ? 1f : 0f);
		}

		private void OnClick()
		{
			VoodooSauceBehaviour.OpenDebugger();
		}

		public void OnPointerDown(PointerEventData ped)
		{
			_startPos = base.transform.position;
			_startMousePos = Input.mousePosition;
			HidePanel.HideChangeState?.Invoke(appear: true);
		}

		public void OnPointerUp(PointerEventData ped)
		{
			if (!_isDragged)
			{
				OnClick();
			}
			SetUpLerp();
			if (RectTransformUtility.RectangleContainsScreenPoint(hideArea, Input.mousePosition))
			{
				HideButtonUI();
			}
			HidePanel.HideChangeState?.Invoke(appear: false);
		}

		public void OnBeginDrag(PointerEventData eventData)
		{
			if (_mouseDownCts != null && _mouseDownCts.Token.CanBeCanceled)
			{
				_mouseDownCts.Cancel();
			}
			_isDragged = true;
		}

		public void OnDrag(PointerEventData eventData)
		{
			if (base.transform.localScale.x < 1.5f)
			{
				base.transform.localScale += new Vector3(0.2f, 0.2f, 0.2f);
			}
			else
			{
				base.transform.localScale = new Vector3(1.5f, 1.5f, 1.5f);
			}
			Vector3 vector = Input.mousePosition - _startMousePos;
			Vector3 position = _startPos + vector;
			base.transform.position = position;
			KeepInsideScreen();
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			_isDragged = false;
			EndOfDragBehavior();
		}
	}
}
